/*
 * Classe des objets Solution qui représente une solution possible du problème
 *
 */

package Modele;

import java.util.LinkedList;

/**
 *
 * @author Kami
 */
public class Solution{

    // Matrice qui représente la solution
    // 0 = pas de lien  (si solMatrice[i][i] = 0 alors i n'est pas dans le cycle )
    // 1 = arc du cycle (si solMatrice[i][i] = 1 alors i est dans le cycle)
    // Si il y a un arc d'assignement de j vers i : solMatrice[j][i] = 2 et solMatrice[i][j] = -2
    //

    private int[][] solMatrice;
    private LinkedList <Integer>cycle = new LinkedList();
    private int coutTotalAssignement;
    private int coutTotalCycle;

    public Solution() {
    }

    	// Constructeur qui prende comme base une autre Solution et fait une copie
	public Solution(Solution modele)
	{
		this.cycle = modele.getCycle();
		this.coutTotalAssignement = modele.getCoutTotalAssignement();
		this.coutTotalCycle = modele.getCoutTotalCycle();

		for(int i = 0; i < modele.getNombreVilles(); i++)
			for(int j = 0; j < modele.getNombreVilles(); j++)
				this.solMatrice[i][j] = modele.getPosMatrice(i, j);
	}

    // Met zero par tout dans la matrice
    public void initialiserMatrice()
    {
        for(int i = 0; i < this.solMatrice.length; i++)
        {
            for(int j = 0; j < this.solMatrice.length; j++)
                this.solMatrice[i][j] = 0;
        }
    }

    public Solution cloner(){
        Solution clone = new Solution();
        clone.solMatrice = this.solMatrice;
        clone.coutTotalCycle = this.coutTotalCycle;
        clone.coutTotalAssignement = this.coutTotalAssignement;
        clone.cycle = this.cycle;
        return clone;
    }

    public LinkedList<Integer> getCycle() {
        return cycle;
    }
  
    public int getCoutTotalAssignement() {
        return coutTotalAssignement;
    }

    public void setCoutTotalAssignement(int coutTotalAssignement) {
        this.coutTotalAssignement = coutTotalAssignement;
    }

    public int getCoutTotalCycle() {
        return coutTotalCycle;
    }

    public void setCoutTotalCycle(int coutTotalCycle) {
        this.coutTotalCycle = coutTotalCycle;
    }

    public int getCoutTotal()
    {
            return this.coutTotalCycle + this.coutTotalAssignement;
    }

    public int[][] getSolMatrice() {
        return solMatrice;
    }

    public void setSolMatrice(int[][] solMatrice) {
        this.solMatrice = solMatrice;
    }

    public void reconstruireCycle(int origine){
        cycle.clear();
        cycle.add(origine);

        int sommetPrecedent = -1;
        int sommetCourant = origine;
        int terminus = -1;


        for (int i=0;i<this.solMatrice.length;i++){
            //System.out.println(i + " : "+solMatrice[origine][i]);
            if (solMatrice[origine][i] == 1 && terminus != -1 && i!=origine){
                sommetCourant = i;
                sommetPrecedent = origine;
                cycle.add(sommetCourant);
            }
            else if (solMatrice[origine][i] == 1 && terminus == -1 && i!=origine){
                terminus = i;
            }
        }

       /* for (int j=0; j<this.solMatrice.length;j++){
                if (solMatrice[sommetCourant][j] == 1 && sommetCourant!=j){System.out.println(sommetCourant + "-" + j);}} */
            

        while (sommetCourant != terminus) {
            for (int i=0; i<this.solMatrice.length;i++) {
                if (solMatrice[sommetCourant][i] == 1 && i!=sommetPrecedent && i!=sommetCourant){
                    sommetPrecedent = sommetCourant;
                    sommetCourant = i;
                    cycle.add(sommetCourant);
                    break;
                }
            }
        }

    }

    // Recupere la valeur qui est dans la position [i, j] de la matrice
    public int getPosMatrice(int ligne, int colomne)
    {
            return this.solMatrice[ligne][colomne];
    }

    // Met une valeur dans la position [i, j]
    public void setPosMatrice(int ligne, int colomne, int valeur)
    {
            this.solMatrice[ligne][colomne] = valeur;
    }

    public int getNombreVilles()
    {
        return this.solMatrice.length;
    }



    public void afficher(){
       
        for (int i=0; i<cycle.size();i++){
           
            int sommetCourant = cycle.get(i);

            System.out.print(sommetCourant + " : ");
            
            for (int a = 0; a < solMatrice.length; a++){
                    if (solMatrice[a][sommetCourant] == 2){
                        System.out.print(a + " ");
                    }
            }
            System.out.println();
        }

        System.out.println("Cout du cycle : " + this.coutTotalCycle);
        System.out.println("Cout d'assignements: " + this.coutTotalAssignement);
    }

    	public int getPremiereVilleCycle()
	{
		for(int ville = 0; ville < this.solMatrice.length; ville++)
			// Si la ville est dans le cycle
			if(this.solMatrice[ville][ville] == 1)
				return ville;

		return -1; // Il n'y a aucune ville dans le cycle
	}
}


